package hr.ctg.service.dao;

import hr.ctg.domain.model.Mjesto;
import hr.ctg.domain.model.Objekt;
import hr.ctg.domain.model.Otok;
import hr.ctg.domain.model.Posjet;
import hr.jpa.dao.GenericDAOImpl;

import java.util.Date;
import java.util.List;

import javax.persistence.NoResultException;

import org.hibernate.Session;
import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;

@AutoCreate
@Name("posjetDAO")
public class PosjetDAO extends GenericDAOImpl<Posjet, Integer> {
	@In
	Session session;

	public Posjet findByObjektDatumPosjete(final Integer idObjekta,
			final Date datumPosjete) {
		try {
			return (Posjet) entityManager.createNamedQuery(
					"Posjet.findByObjektDatumPosjete").setParameter(1,
					idObjekta).setParameter(2, datumPosjete).getSingleResult();
		} catch (final NoResultException e) {
			return null;
		}
	}

	public Posjet findByMjestoDatumPosjete(final Integer idMjesta,
			final Date datumPosjete) {
		try {
			return (Posjet) entityManager.createNamedQuery(
					"Posjet.findByMjestoDatumPosjete")
					.setParameter(1, idMjesta).setParameter(2, datumPosjete)
					.getSingleResult();
		} catch (final NoResultException e) {
			return null;
		}
	}

	public Posjet findByOtokDatumPosjete(final Integer idOtoka,
			final Date datumPosjete) {
		try {
			return (Posjet) entityManager.createNamedQuery(
					"Posjet.findByOtokDatumPosjete").setParameter(1, idOtoka)
					.setParameter(2, datumPosjete).getSingleResult();
		} catch (final NoResultException e) {
			return null;
		}
	}

	@SuppressWarnings("unchecked")
	public List<Mjesto> findTopMjestaByPosjetMjesta(int top, Date startDate,
			Date endDate) {
		/*
		 * session.enableFilter("periodPosjeteFilter").setParameter("startDate",
		 * startDate).setParameter("endDate", endDate);
		 */
		return entityManager
				.createNativeQuery(
						"select mjesto1_.id_mjesta, mjesto1_.grad, mjesto1_.latituda, mjesto1_.longituda, mjesto1_.naziv, mjesto1_.opis, mjesto1_.id_otoka, mjesto1_.panoramio, mjesto1_.id_poste, mjesto1_.www, mjesto1_.zoom, mjesto1_.id_zupanije from (SELECT id_mjesta FROM posjet where id_mjesta is not null and datum_posjete BETWEEN DATE_SUB(CURRENT_DATE,INTERVAL 1 MONTH) AND CURRENT_DATE group by id_mjesta order by sum(broj_posjeta) desc limit ?1) posjet0_  inner join mjesto mjesto1_ on posjet0_.id_mjesta=mjesto1_.id_mjesta",
						Mjesto.class).setParameter(1, top).getResultList();
		/*
		 * return session.getNamedQuery("Posjet.findTopMjestaByPosjetMjesta")
		 * .setMaxResults(top).list();
		 */
	}

	@SuppressWarnings("unchecked")
	public List<Mjesto> findTopMjestaByOcjena(int top, Date startDate,
			Date endDate) {
		session.enableFilter("periodPosjeteFilter").setParameter("startDate",
				startDate).setParameter("endDate", endDate);

		return session.getNamedQuery("Posjet.findTopMjestaByOcjena")
				.setMaxResults(top).list();
	}

	@SuppressWarnings("unchecked")
	public List<Otok> findTopOtociByOcjena(int top, Date startDate, Date endDate) {
		session.enableFilter("periodPosjeteFilter").setParameter("startDate",
				startDate).setParameter("endDate", endDate);

		return session.getNamedQuery("Posjet.findTopOtociByOcjena")
				.setMaxResults(top).list();
	}

	@SuppressWarnings("unchecked")
	public List<Otok> findTopOtociByPosjetOtoka(int top, Date startDate,
			Date endDate) {
		session.enableFilter("periodPosjeteFilter").setParameter("startDate",
				startDate).setParameter("endDate", endDate);

		return session.getNamedQuery("Posjet.findTopOtociByPosjetMjesta")
				.setMaxResults(top).list();
	}

	@SuppressWarnings("unchecked")
	public List<Objekt> findTopObjektiByOcjenaIdTipaObjekta(
			Integer idTipaObjekta, int top, Date startDate, Date endDate) {
		session.enableFilter("periodPosjeteFilter").setParameter("startDate",
				startDate).setParameter("endDate", endDate);

		return session.getNamedQuery(
				"Posjet.findTopObjektiByOcjenaIdTipaObjekta").setParameter(0,
				idTipaObjekta).setMaxResults(top).list();
	}

	@SuppressWarnings("unchecked")
	public List<Objekt> findTopObjektiByPosjetObjektaIdTipaObjekta(
			Integer idTipaObjekta, int top, Date startDate, Date endDate) {
		session.enableFilter("periodPosjeteFilter").setParameter("startDate",
				startDate).setParameter("endDate", endDate);

		return session.getNamedQuery(
				"Posjet.findTopObjektiByPosjetObjektaIdTipaObjekta")
				.setParameter(0, idTipaObjekta).setMaxResults(top).list();
	}

	@SuppressWarnings("unchecked")
	public List<Mjesto> findTopMjestaByOcjenaIdOtoka(Integer idOtoka, int top,
			Date startDate, Date endDate) {
		session.enableFilter("periodPosjeteFilter").setParameter("startDate",
				startDate).setParameter("endDate", endDate);

		return session.getNamedQuery("Posjet.findTopMjestaByOcjenaIdOtoka")
				.setParameter(0, idOtoka).setMaxResults(top).list();
	}

	@SuppressWarnings("unchecked")
	public List<Mjesto> findTopMjestaByPosjetMjestaIdOtoka(Integer idOtoka,
			int top, Date startDate, Date endDate) {
		session.enableFilter("periodPosjeteFilter").setParameter("startDate",
				startDate).setParameter("endDate", endDate);

		return session.getNamedQuery(
				"Posjet.findTopMjestaByPosjetMjestaIdOtoka").setParameter(0,
				idOtoka).setMaxResults(top).list();
	}

	@SuppressWarnings("unchecked")
	public List<Mjesto> findTopMjestaByOcjenaIdZupanije(Integer idZupanije,
			int top, Date startDate, Date endDate) {
		session.enableFilter("periodPosjeteFilter").setParameter("startDate",
				startDate).setParameter("endDate", endDate);

		return session.getNamedQuery("Posjet.findTopMjestaByOcjenaIdZupanije")
				.setParameter(0, idZupanije).setMaxResults(top).list();
	}

	@SuppressWarnings("unchecked")
	public List<Mjesto> findTopMjestaByPosjetMjestaIdZupanije(
			Integer idZupanije, int top, Date startDate, Date endDate) {
		session.enableFilter("periodPosjeteFilter").setParameter("startDate",
				startDate).setParameter("endDate", endDate);

		return session.getNamedQuery(
				"Posjet.findTopMjestaByPosjetMjestaIdZupanije").setParameter(0,
				idZupanije).setMaxResults(top).list();
	}

	@SuppressWarnings("unchecked")
	public List<Otok> findTopOtociByOcjenaIdZupanije(Integer idZupanije,
			int top, Date startDate, Date endDate) {
		session.enableFilter("periodPosjeteFilter").setParameter("startDate",
				startDate).setParameter("endDate", endDate);

		return session.getNamedQuery("Posjet.findTopOtociByOcjenaIdZupanije")
				.setParameter(0, idZupanije).setMaxResults(top).list();
	}

	@SuppressWarnings("unchecked")
	public List<Otok> findTopOtociByPosjetOtokaIdZupanije(Integer idZupanije,
			int top, Date startDate, Date endDate) {
		session.enableFilter("periodPosjeteFilter").setParameter("startDate",
				startDate).setParameter("endDate", endDate);

		return session.getNamedQuery(
				"Posjet.findTopOtociByPosjetOtokaIdZupanije").setParameter(0,
				idZupanije).setMaxResults(top).list();
	}

	@SuppressWarnings("unchecked")
	public List<Objekt> findTopObjektiByOcjenaIdMjestaIdTipaObjekta(
			Integer idMjesta, Integer idTipaObjekta, Integer top,
			Date startDate, Date endDate) {
		session.enableFilter("periodPosjeteFilter").setParameter("startDate",
				startDate).setParameter("endDate", endDate);

		return session.getNamedQuery(
				"Posjet.findTopObjektiByOcjenaIdMjestaIdTipaObjekta")
				.setParameter(0, idMjesta).setParameter(1, idTipaObjekta)
				.setMaxResults(top).list();
	}

	@SuppressWarnings("unchecked")
	public List<Objekt> findTopObjektiByPosjetObjektaIdMjestaIdTipaObjekta(
			Integer idMjesta, Integer idTipaObjekta, Integer top,
			Date startDate, Date endDate) {
		session.enableFilter("periodPosjeteFilter").setParameter("startDate",
				startDate).setParameter("endDate", endDate);

		return session.getNamedQuery(
				"Posjet.findTopObjektiByPosjetObjektaIdMjestaIdTipaObjekta")
				.setParameter(0, idMjesta).setParameter(1, idTipaObjekta)
				.setMaxResults(top).list();
	}

	@SuppressWarnings("unchecked")
	public List<Objekt> findTopObjektiByOcjenaIdOtokaIdTipaObjekta(
			Integer idOtoka, Integer idTipaObjekta, Integer top,
			Date startDate, Date endDate) {
		session.enableFilter("periodPosjeteFilter").setParameter("startDate",
				startDate).setParameter("endDate", endDate);

		return session.getNamedQuery(
				"Posjet.findTopObjektiByOcjenaIdOtokaIdTipaObjekta")
				.setParameter(0, idTipaObjekta).setParameter(1, idOtoka)
				.setMaxResults(top).list();
	}

	@SuppressWarnings("unchecked")
	public List<Objekt> findTopObjektiByPosjetObjektaIdOtokaIdTipaObjekta(
			Integer idOtoka, Integer idTipaObjekta, Integer top,
			Date startDate, Date endDate) {
		session.enableFilter("periodPosjeteFilter").setParameter("startDate",
				startDate).setParameter("endDate", endDate);

		return session.getNamedQuery(
				"Posjet.findTopObjektiByPosjetObjektaIdOtokaIdTipaObjekta")
				.setParameter(0, idTipaObjekta).setParameter(1, idOtoka)
				.setMaxResults(top).list();
	}

	@SuppressWarnings("unchecked")
	public List<Objekt> findTopObjektiByOcjenaIdZupanijeIdTipaObjekta(
			int idTipaObjekta, Integer idZupanije, int top, Date startDate,
			Date endDate) {
		session.enableFilter("periodPosjeteFilter").setParameter("startDate",
				startDate).setParameter("endDate", endDate);

		return session.getNamedQuery(
				"Posjet.findTopObjektiByOcjenaIdZupanijeIdTipaObjekta")
				.setParameter(0, idTipaObjekta).setParameter(1, idZupanije)
				.setMaxResults(top).list();
	}

	@SuppressWarnings("unchecked")
	public List<Objekt> findTopObjektiByPosjetObjektaIdZupanijeIdTipaObjekta(
			int idTipaObjekta, Integer idZupanije, int top, Date startDate,
			Date endDate) {
		session.enableFilter("periodPosjeteFilter").setParameter("startDate",
				startDate).setParameter("endDate", endDate);

		return session.getNamedQuery(
				"Posjet.findTopObjektiByPosjetObjektaIdZupanijeIdTipaObjekta")
				.setParameter(0, idTipaObjekta).setParameter(1, idZupanije)
				.setMaxResults(top).list();
	}

	public long findCountTopObjektiByPosjetiIdOtoka(final Integer idOtoka,
			Date startDate, Date endDate) {
		session.enableFilter("periodPosjeteFilter").setParameter("startDate",
				startDate).setParameter("endDate", endDate);
		try {
			return (Long) session.getNamedQuery(
					"Posjet.findCountTopObjektiByPosjetiIdOtoka").setParameter(
					0, idOtoka).uniqueResult();
		} catch (final NoResultException e) {
			return 0;
		}
	}

	public long findCountTopObjektiByOcjenaIdOtoka(final Integer idOtoka,
			Date startDate, Date endDate) {
		try {
			return (Long) entityManager.createNamedQuery(
					"Posjet.findCountTopObjektiByOcjenaIdOtoka").setParameter(
					1, idOtoka).getSingleResult();
		} catch (final NoResultException e) {
			return 0;
		}
	}

	public long findCountTopObjektiByPosjetiIdMjesta(final Integer idMjesta,
			Date startDate, Date endDate) {
		try {
			return (Long) entityManager.createNamedQuery(
					"Posjet.findCountTopObjektiByPosjetiIdMjesta")
					.setParameter(1, idMjesta).getSingleResult();
		} catch (final NoResultException e) {
			return 0;
		}
	}

	public long findCountTopObjektiByOcjenaIdMjesta(final Integer idMjesta,
			Date startDate, Date endDate) {
		try {
			return (Long) entityManager.createNamedQuery(
					"Posjet.findCountTopObjektiByOcjenaIdMjesta").setParameter(
					1, idMjesta).getSingleResult();
		} catch (final NoResultException e) {
			return 0;
		}
	}

	public long findCountTopObjektiByPosjetiIdZupanije(
			final Integer idZupanije, Date startDate, Date endDate) {
		try {
			return (Long) entityManager.createNamedQuery(
					"Posjet.findCountTopObjektiByPosjetiIdZupanije")
					.setParameter(1, idZupanije).getSingleResult();
		} catch (final NoResultException e) {
			return 0;
		}
	}

	public long findCountTopObjektiByOcjenaIdZupanije(final Integer idZupanije,
			Date startDate, Date endDate) {
		try {
			return (Long) entityManager.createNamedQuery(
					"Posjet.findCountTopObjektiByOcjenaIdZupanije")
					.setParameter(1, idZupanije).getSingleResult();
		} catch (final NoResultException e) {
			return 0;
		}
	}

	public long findCountTopObjektiByOcjena(Date startDate, Date endDate) {
		try {
			return (Long) entityManager.createNamedQuery(
					"Posjet.findCountTopObjektiByOcjena").getSingleResult();
		} catch (final NoResultException e) {
			return 0;
		}
	}

	public long findCountTopObjektiByPosjeti(Date startDate, Date endDate) {
		try {
			return (Long) entityManager.createNamedQuery(
					"Posjet.findCountTopObjektiByPosjeti").getSingleResult();
		} catch (final NoResultException e) {
			return 0;
		}
	}

	@SuppressWarnings("unchecked")
	public List<Mjesto> findTopMjestaByOcjenaIdTipaObjekta(
			final Integer idTipaObjekta, final Integer max, Date startDate,
			Date endDate) {
		session.enableFilter("periodPosjeteFilter").setParameter("startDate",
				startDate).setParameter("endDate", endDate);
		return session.getNamedQuery(
				"Posjet.findToMjestapByOcjenaIdTipaObjekta").setParameter(0,
				idTipaObjekta).setMaxResults(max).list();
	}

	@SuppressWarnings("unchecked")
	public List<Mjesto> findTopMjestaByPosjetObjektaIdTipaObjekta(
			final Integer idTipaObjekta, final Integer max, Date startDate,
			Date endDate) {
		session.enableFilter("periodPosjeteFilter").setParameter("startDate",
				startDate).setParameter("endDate", endDate);
		return session.getNamedQuery(
				"Posjet.findTopMjestaByPosjetObjektaIdTipaObjekta")
				.setParameter(0, idTipaObjekta).setMaxResults(max).list();
	}
}